#ifndef lista_h
#define lista_h
#include <iostream>
#include "NodoLista.h"


using namespace :: std;

template<class t_nodo>
class Lista{
      private:
              NodoLista< t_nodo > * primero;
              NodoLista< t_nodo > * ultimo;
      public:
             Lista();
             ~Lista();
             
             void push_front(const t_nodo &);
             void push_back(const t_nodo &);
             bool pop_front();
             bool pop_back();
             void clear();
             bool empty() const;
             
             t_nodo & front() const;
             t_nodo & back() const;
             
};

template<class t_nodo>
Lista<t_nodo> :: Lista(){
    primero = ultimo = 0;
}

template<class t_nodo>
Lista<t_nodo> :: ~Lista(){
}

template<class t_nodo>
void Lista<t_nodo> :: push_front( const t_nodo & valor ){
     NodoLista<t_nodo> * nuevoPtr = new NodoLista < t_nodo > (valor);
     
     if(empty())
         primero = ultimo = nuevoPtr;
     else{
          nuevoPtr->sig = primero;
          primero = nuevoPtr;
     }
}

template<class t_nodo>
void Lista<t_nodo> :: push_back(const t_nodo &valor){
     NodoLista<t_nodo> *nuevoPtr = new NodoLista<t_nodo>(valor);
     
     if(empty())
         primero = ultimo = nuevoPtr;
     else{
          ultimo->sig = nuevoPtr;
          ultimo = nuevoPtr;
     }
}

template<class t_nodo>
bool Lista<t_nodo> :: pop_front(){
    
     if(empty())
         return false;
     else{
          NodoLista<t_nodo> *tempPtr = primero;
          
          if(primero == ultimo)
              primero = ultimo = 0;
          else
              primero = primero->sig;
          
          delete tempPtr;      
          return true;
     }
     
}

template<class t_nodo>
bool Lista<t_nodo> :: pop_back(){
     if(empty())
         return false;
     else{
          NodoLista<t_nodo> *tempPtr = ultimo;
          
          if(primero == ultimo)
              primero = ultimo = 0;
          else{
               NodoLista<t_nodo> *actualPtr = primero;
               
               while(actualPtr->sig != ultimo)
                   actualPtr = actualPtr->sig;
               
               ultimo = actualPtr;
               actualPtr->sig = 0;
          }
 
          delete tempPtr;   
          return true;
     }
}

template<class t_nodo>
bool Lista<t_nodo> :: empty() const{
     return primero == 0;
}

template<class t_nodo>
t_nodo & Lista<t_nodo> :: front() const{
    return primero->dato;
}

template<class t_nodo>
t_nodo & Lista<t_nodo> :: back() const{
    return ultimo->dato;
}

template<class t_nodo>
void Lista<t_nodo> :: clear(){
    
   if(!empty()){
        
        NodoLista < t_nodo > * actual = primero;
        NodoLista < t_nodo > * temp = 0;
        
    
        while( actual ){
            temp = actual;
            actual = actual->sig;
            delete temp;
        }
        
    }
    
    primero = ultimo = 0;
}

#endif
